package mudclient;

import java.util.concurrent.ConcurrentLinkedQueue;

import javax.swing.JOptionPane;

public class ReadProcessingThread extends Thread {

	public ReadProcessingThread(MudClientTextPane itp) {
		super();
		this.itp = itp;
		q = new ConcurrentLinkedQueue<byte[]>();
	}

	public void run() {
		while(r) {
			if(q.size() > 0)
				processTelnet(q.poll());
			if(q.size() == 0)
				if(r)
					synchronized(this) {
						paused = true;
						try {
							while(paused)
								wait();
						} catch (InterruptedException e) {
							JOptionPane.showMessageDialog(MudClientApplication
									.getMainFrame(), e.getMessage());
						}
					}
		}
	}
	
	public synchronized void setRunning(boolean r) {
		this.r = r;
	}
	
	public synchronized void addText(byte[] b) {
		q.add(b);
		if(paused)
			synchronized(this) {
				paused = false;
				notifyAll();
			}
	}
	
	private void processTelnet(byte[] t) {
		int l = t.length;
		byte[] d = new byte[l];
		int x = 0;
		for(int p = 0; p < l; p++) {
			byte b = t[p];
			if (b == IAC && p < (l - 2)) {
				p += 2;
			} else if (b == ESC) {
				w = true;
				if (x != 0) {
					itp.appendString(new String(d, 0, x));
					d = new byte[l - p];
					x = 0;
				}
			} else if (w) {
				if(b != BRACKET) {
					if(b == M) {
						if(lastCode != -1) {
							itp.setAnsiStyle(Integer.parseInt((char)lastCode + ""));
							lastCode = -1;
						}
						w = false;
					} else if (b == SEMICOLON) {
						if(lastCode != -1) {
							itp.setAnsiStyle(Integer.parseInt((char)lastCode + ""));
							lastCode = -1;
						}
					} else {
						if (lastCode == -1)
							lastCode = b;
						else {
							itp.setAnsiStyle(Integer.parseInt((char)lastCode + "" + (char)b));
							lastCode = -1;
						}
					}
				}
			} else {
				d[x] = b;
				x++;
			}
		}
		if(x != 0) {
			itp.appendString(new String(d, 0, x));
		}
    }
	
	private volatile boolean r = true;
	private MudClientTextPane itp;
	private boolean w = false;
	private int lastCode = -1;
	private boolean paused ;
	private ConcurrentLinkedQueue<byte[]> q;
	
	final private byte IAC = (byte)255;
	final private byte M = (byte)109;
	final private byte SEMICOLON = (byte)59;
	final private byte BRACKET = (byte)91;
	final private byte ESC = (byte)27;
}
